﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using ReportWizard.Helpers;
using ReportWizard.Interface;
using ReportWizard.Properties;

namespace ReportWizard.DataAccess
{
    public class ReportBaseObject
    {
        public int Id { get; private set; }
        public int WordBookmarkId { get; set; }
        public int BookmarkGroupId { get; set; }
        public string Name { get; set; }
        public DateTime DateCreated { get; private set; }
        public bool Visible { get; set; }
        public bool Deleted { get; private set; }

        private ReportBaseObject()
        {

        }

        public ReportBaseObject(int bookmarkId, string name, bool isGroup, bool visible = true)
        {
            WordBookmarkId = isGroup ? 0 : bookmarkId;
            BookmarkGroupId = isGroup ? bookmarkId : 0;
            Name = name;
            Visible = visible;
        }

        public ReportBaseObject(int id, int bookmarkId, string name, bool isGroup, bool visible = true)
        {
            Id = id;
            WordBookmarkId = isGroup ? 0 : bookmarkId;
            BookmarkGroupId = isGroup ? bookmarkId : 0;
            Name = name;
            Visible = visible;
        }

        public void Insert(bool alertIfExist, bool isGroup)
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    if (!IsExist(isGroup))
                    {

                        SqlCommand saveCmd = new SqlCommand("ReportBaseObjectInsert", con);
                        saveCmd.CommandType = CommandType.StoredProcedure;

                        saveCmd.Parameters.Add("@BookmarkId", SqlDbType.Int).Value = isGroup ? BookmarkGroupId : WordBookmarkId;
                        saveCmd.Parameters.Add("@IsGroup", SqlDbType.Bit).Value = isGroup;
                        saveCmd.Parameters.Add("@Name", SqlDbType.VarBinary).Value = Crypto.Encrypt(Name);
                        saveCmd.Parameters.Add("@Visible", SqlDbType.Bit).Value = Visible;
                        saveCmd.Parameters.Add("@Id", SqlDbType.Int).Direction =
                            ParameterDirection.Output;

                        con.Open();

                        bool isRowsAffected = saveCmd.ExecuteNonQuery() > 0;
                        if (isRowsAffected)
                        {
                            Id = Convert.ToInt32(saveCmd.Parameters["@Id"].Value);
                            IBookmark ib = isGroup ? (IBookmark)BookmarkGroup.Select(BookmarkGroupId) : WordBookmark.Select(WordBookmarkId);
                            if (ib != null)
                            {
                                HistoryRecord hr = new HistoryRecord
                                                       {
                                                           Action = HistoryEvent.SelectObjectAdd,
                                                           Description =
                                                               string.Format(
                                                                   "Для {0} [{1}] добавлено значение выбора [{2}]",
                                                                   ib is WordBookmark ? "закладки" : "группы закладок",
                                                                   ib.Name,
                                                                   Name)
                                                       };
                                hr.Insert();
                            }
                        }
                    }
                    else
                    {
                        if (alertIfExist)
                        {
                            ShowMessage.Error(Resources.SameRecordIsExist);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
            }
        }

        public static bool Delete(int id)
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    SqlCommand delCmd = new SqlCommand("ReportBaseObjectDelete", con);
                    delCmd.CommandType = CommandType.StoredProcedure;

                    delCmd.Parameters.Add("@Id", SqlDbType.Int).Value = id;
                    con.Open();

                    bool isRowsAffected = delCmd.ExecuteNonQuery() > 0;
                    if (isRowsAffected)
                    {
                        ReportBaseObject rbo = Select(id);
                        if (rbo != null)
                        {
                            IBookmark ib = rbo.WordBookmarkId != 0 ? (IBookmark)WordBookmark.Select(rbo.WordBookmarkId) : BookmarkGroup.Select(rbo.BookmarkGroupId);
                            if (ib != null)
                            {
                                HistoryRecord hr = new HistoryRecord
                                                       {
                                                           Action = HistoryEvent.SelectOjectRemove,
                                                           Description =
                                                               string.Format(
                                                                   "Для {0} [{1}] удалено значение выбора [{2}]",
                                                                   ib is WordBookmark ? "закладки" : "группы закладок",
                                                                   ib.Name,
                                                                   rbo.Name)
                                                       };
                                hr.Insert();
                            }
                        }
                    }

                    return isRowsAffected;
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return false;
            }
        }

        public static bool DeleteAllInBookmark(int bookmarkId, bool isGroup)
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    SqlCommand delCmd = new SqlCommand("ReportBaseObjectDeleteAllInBookmark", con);
                    delCmd.CommandType = CommandType.StoredProcedure;

                    delCmd.Parameters.Add("@BookmarkId", SqlDbType.Int).Value = bookmarkId;
                    delCmd.Parameters.Add("@IsGroup", SqlDbType.Bit).Value = isGroup;
                    con.Open();

                    bool isRowsAffected = delCmd.ExecuteNonQuery() > 0;
                    if (isRowsAffected)
                    {
                        IBookmark ib = isGroup ? (IBookmark)BookmarkGroup.Select(bookmarkId) : WordBookmark.Select(bookmarkId);
                        if (ib != null)
                        {
                            HistoryRecord hr = new HistoryRecord
                            {
                                Action = HistoryEvent.SelectOjectRemove,
                                Description =
                                    string.Format(
                                        "Для {0} [{1}] удалены все значения выбора",
                                        ib is WordBookmark ? "закладки" : "группы закладок",
                                        ib.Name)
                            };
                            hr.Insert();
                        }

                    }

                    return isRowsAffected;
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return false;
            }
        }

        public static ReportBaseObject Select(int id)
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    SqlCommand getCmd = new SqlCommand("ReportBaseObjectSelect", con);
                    getCmd.CommandType = CommandType.StoredProcedure;

                    getCmd.Parameters.Add("@Id", SqlDbType.Int).Value = id;

                    con.Open();
                    List<ReportBaseObject> cList = MapFrom(getCmd.ExecuteReader());
                    return cList != null ? cList.FirstOrDefault() : null;
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return null;
            }
        }

        public static List<ReportBaseObject> Select(bool onlyVisible, int bookmarkId, bool isGroup)
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    SqlCommand getCmd = new SqlCommand("ReportBaseObjectSelectAll", con);
                    getCmd.CommandType = CommandType.StoredProcedure;

                    getCmd.Parameters.Add("@BookmarkId", SqlDbType.Int).Value = bookmarkId;
                    getCmd.Parameters.Add("@IsGroup", SqlDbType.Bit).Value = isGroup;
                    getCmd.Parameters.Add("@OnlyVisible", SqlDbType.Bit).Value = onlyVisible;

                    con.Open();
                    return MapFrom(getCmd.ExecuteReader());
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return null;
            }
        }

        private bool IsExist(bool isGroup)
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    SqlCommand getCmd = new SqlCommand("ReportBaseObjectIsExist", con);
                    getCmd.CommandType = CommandType.StoredProcedure;

                    getCmd.Parameters.Add("@BookmarkId", SqlDbType.Int).Value = isGroup ? BookmarkGroupId : WordBookmarkId;
                    getCmd.Parameters.Add("@IsGroup", SqlDbType.Bit).Value = isGroup;
                    getCmd.Parameters.Add("@Name", SqlDbType.VarBinary).Value = Crypto.Encrypt(Name);

                    con.Open();
                    return Convert.ToInt32(getCmd.ExecuteScalar()) > 0;
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return true;
            }
        }

        private static List<ReportBaseObject> MapFrom(SqlDataReader dr)
        {
            try
            {
                if (dr != null && dr.HasRows)
                {
                    List<ReportBaseObject> acList = new List<ReportBaseObject>();
                    while (dr.Read())
                    {
                        ReportBaseObject rbo = new ReportBaseObject
                                                   {
                                                       Id = Convert.ToInt32(dr["Id"]),
                                                       Name = Crypto.Decrypt((byte[])dr["Name"]),
                                                       WordBookmarkId = dr["WordBookmarkId"] != DBNull.Value ? Convert.ToInt32(dr["WordBookmarkId"]) : 0,
                                                       BookmarkGroupId = dr["BookmarkGroupId"] != DBNull.Value ? Convert.ToInt32(dr["BookmarkGroupId"]) : 0,
                                                       DateCreated = Convert.ToDateTime(dr["DateCreated"]),
                                                       Visible = Convert.ToBoolean(dr["Visible"])
                                                   };

                        acList.Add(rbo);
                    }
                    return acList;
                }
                return null;
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return null;
            }
        }
    }
}